Fix a cpufreq userspace limitation bug
authorKeir Fraser <keir.fraser@citrix.com>
Thu, 19 Mar 2009 10:09:24 +0000 (10:09 +0000)
committerKeir Fraser <keir.fraser@citrix.com>
Thu, 19 Mar 2009 10:09:24 +0000 (10:09 +0000)
Fix a cpufreq userspace limitation bug, so that userspace freq can
return to correct freq when freq_limitation return to high value (like
ppc event)

Signed-off-by: Liu, Jinsong <jinsong.liu@intel.com>=
xen/drivers/acpi/pmstat.c
xen/drivers/cpufreq/cpufreq_misc_governors.c
xen/include/acpi/cpufreq/cpufreq.h

index f2aaca7c24af886c6eab73c08bfc520cb7468ec6..bf476d584d82d033b00304d5254f5db5fdfc128e 100644 (file)
@@ -368,14 +368,7 @@ static int set_cpufreq_para(struct xen_sysctl_pm_op *op)
 
         if ( !strnicmp(policy->governor->name,
                        "userspace", CPUFREQ_NAME_LEN) )
-        {
-            if ( freq < policy->min )
-                freq = policy->min;
-            if ( freq > policy->max )
-                freq = policy->max;
-
-            ret = __cpufreq_driver_target(policy, freq, CPUFREQ_RELATION_L);
-        }
+            ret = write_userspace_scaling_setspeed(op->cpuid, freq);
         else
             ret = -EINVAL;
 
index a375a25bb95028913cb74680c989f931b1b49895..1c63ec18154ddf92712c28cf0d08ef686794d3f7 100644 (file)
 #include <xen/sched.h>
 #include <acpi/cpufreq/cpufreq.h>
 
-static unsigned int usr_speed;
-
 /*
  * cpufreq userspace governor
  */
+static unsigned int cpu_set_freq[NR_CPUS];
+
 static int cpufreq_governor_userspace(struct cpufreq_policy *policy,
                                       unsigned int event)
 {
     int ret = 0;
-    unsigned int freq;
+    unsigned int cpu;
 
-    if (!policy)
+    if (unlikely(!policy) || 
+        unlikely(!cpu_online(cpu = policy->cpu)))
         return -EINVAL;
 
     switch (event) {
     case CPUFREQ_GOV_START:
+        if (!cpu_set_freq[cpu])
+            cpu_set_freq[cpu] = policy->cur;
+        break;
     case CPUFREQ_GOV_STOP:
+        cpu_set_freq[cpu] = 0;
         break;
     case CPUFREQ_GOV_LIMITS:
-        freq = usr_speed ? : policy->cur;
-        if (policy->max < freq)
+        if (policy->max < cpu_set_freq[cpu])
             ret = __cpufreq_driver_target(policy, policy->max,
                         CPUFREQ_RELATION_H);
-        else if (policy->min > freq)
+        else if (policy->min > cpu_set_freq[cpu])
             ret = __cpufreq_driver_target(policy, policy->min,
                         CPUFREQ_RELATION_L);
-        else if (usr_speed)
-            ret = __cpufreq_driver_target(policy, freq,
+        else
+            ret = __cpufreq_driver_target(policy, cpu_set_freq[cpu],
                         CPUFREQ_RELATION_L);
 
         break;
@@ -57,11 +61,34 @@ static int cpufreq_governor_userspace(struct cpufreq_policy *policy,
     return ret;
 }
 
+int write_userspace_scaling_setspeed(unsigned int cpu, unsigned int freq)
+{
+    struct cpufreq_policy *policy = cpufreq_cpu_policy[cpu];
+
+    if (!cpu_online(cpu) || !policy)
+        return -EINVAL;
+
+    cpu_set_freq[cpu] = freq;
+
+    if (freq < policy->min)
+        freq = policy->min;
+    if (freq > policy->max)
+        freq = policy->max;
+
+    return __cpufreq_driver_target(policy, freq, CPUFREQ_RELATION_L);
+}
+
 static void __init 
 cpufreq_userspace_handle_option(const char *name, const char *val)
 {
-    if (!strcmp(name, "speed") && val)
-        usr_speed = simple_strtoul(val, NULL, 0);
+    if (!strcmp(name, "speed") && val) {
+        unsigned int usr_cmdline_freq;
+        unsigned int cpu;
+
+        usr_cmdline_freq = simple_strtoul(val, NULL, 0);
+        for (cpu = 0; cpu < NR_CPUS; cpu++)
+            cpu_set_freq[cpu] = usr_cmdline_freq;
+    }
 }
 
 struct cpufreq_governor cpufreq_gov_userspace = {
index 93acc7a4e0bcd6bb5e006c0063669e54d4eb16af..bc525862bcbe0aa44e9115b1b899dafc380b787b 100644 (file)
@@ -227,4 +227,6 @@ int get_cpufreq_ondemand_para(uint32_t *sampling_rate_max,
                               uint32_t *up_threshold);
 int write_ondemand_sampling_rate(unsigned int sampling_rate);
 int write_ondemand_up_threshold(unsigned int up_threshold);
+
+int write_userspace_scaling_setspeed(unsigned int cpu, unsigned int freq);
 #endif /* __XEN_CPUFREQ_PM_H__ */